package com.thinkTank.oa.util;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.github.pagehelper.StringUtil;
import com.thinkTank.oa.common.Constant;
import com.thinkTank.oa.common.SystemGlobals;
import com.thinkTank.oa.entity.Demand;
import com.thinkTank.oa.entity.Dictiontry;
import com.thinkTank.oa.entity.ImportDemand;
import com.thinkTank.oa.entity.ImportProject;
import com.thinkTank.oa.entity.Person;
import com.thinkTank.oa.entity.Project;
import com.thinkTank.oa.entity.ProjectAttr;

import freemarker.template.Configuration;

/**
 * 其他库没有的分组，使用项目库的分组
 * @author pdz
 * @date 2018年9月11日
 */
public class ExcelUtil {
	
	/**
	 * 写入excel
	 * @param tagList 标题list
	 * @param contentLists 内容list，每一行记录都是一个list，注意和标题顺序对应，所有的list放在一个list中
	 * @param excelName excel文件名，不要带路径，以xls结束
	 */
	public static File writeExcel(List<String> tagList, List<List<String>> contentLists, String excelName) {
		return writeExcel(tagList, contentLists, excelName, "sheet0");
	}
	
	/**
	 * 写入excel
	 * @param tagList 表头list
	 * @param contentLists 内容list，每一行记录都是一个list，注意和标题顺序对应，所有的内容行list放在一个list中
	 * @param excelName excel文件名，不要带路径，以xls结束
	 * @param sheetName sheet名称
	 */
	public static File writeExcel(List<String> tagList, List<List<String>> contentLists, String excelName, String sheetName) {
		File file = new File(excelName);
		Workbook workbook = new HSSFWorkbook();
		Sheet sheet = workbook.createSheet(sheetName);
		//写入标题行
		writeRow(sheet.createRow(0), tagList);
		//写入内容行
		IntStream.range(0, contentLists.size()).forEach(i -> writeRow(sheet.createRow(i+1), contentLists.get(i)));
		//写入excel
		try(OutputStream out = new FileOutputStream(file)) {
			workbook.write(out);
			workbook.close();
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return file;
	}

	/**
	 * 写入行
	 * @param row 行
	 * @param rowList 要写入到行的内容
	 */
	private static void writeRow(Row row, List<String> rowList) {
		IntStream.range(0, rowList.size()).forEach(i -> row.createCell(i).setCellValue(rowList.get(i)));
	}
	
    
    /**
     * 读取excel，从第2行开始读取，每一行从第一列开始读取，如果没有值，会返回一个empty list
     * @author pdz
     * @date 2018年9月4日
     * @param in
     * @return
     */
    public static List<List<String>> readExcel(InputStream in) {
        List<List<String>> contentLists = new LinkedList<>();
        try(Workbook workbook = new XSSFWorkbook(in);) {
            Sheet sheet = workbook.getSheetAt(0);
            int lastCellNum = sheet.getRow(0).getLastCellNum();
            int lastRowNum = sheet.getLastRowNum();
            System.out.println("最后一行是：" + lastRowNum);
            for (int i = 1; i <= lastRowNum; i++) {
            	System.out.println("read-" + (i+1));
                Row row = sheet.getRow(i);
                List<String> list = IntStream.rangeClosed(0, lastCellNum).boxed()
                        .map(n -> getCellValue(row, n)).collect(Collectors.toList());
                contentLists.add(list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return contentLists;
    }

    private static String getCellValue(Row row, int cellnum) {
    	System.out.println("col-"+(cellnum+1));
        Cell cell = row.getCell(cellnum);
        if (cell == null)
            return null;
        CellType cellType = cell.getCellTypeEnum();
        String cellValue = cellType == CellType.NUMERIC ? new DecimalFormat("#").format(cell.getNumericCellValue()) : cell.getStringCellValue();
        return cellValue;
    }
    
    /**
     * 将从excel中读取的每一行转换成一个ImportProject对象<br/>
     * 表头格式必须如下：<br/>
     * 项目来源  来源备注    项目类型    所属领域    国内或国外   所在地区    项目名称    项目简介    项目关键词   项目持有人   市场前景    技术成熟程度  项目需求    联系人   固定电话    手机  邮箱  微信  其他联系方式<br/>
     * 所在地区格式如：湖北-武汉<br/>
     * @author pdz
     * @date 2018年9月4日
     * @param in
     * @return
     */
    public static List<ImportProject> readImportProjectList(InputStream in) {
        List<ImportProject> importProjectList = new LinkedList<>();
        List<List<String>> contentLists = readExcel(in);
        contentLists.forEach(contentList -> importProjectList.add(createImportProject(contentList)));
        return importProjectList;
    }
    
    private static ImportProject createImportProject(List<String> contentList) {
        Project pro = new Project();
        pro.setSourceId(getDicPid(contentList.get(0), Constant.DICTIONTRY_PROJECTSOURCE));
        pro.setSourceRemark(contentList.get(1));
        //项目类型不存在未其他（3）
        String projectType = getCheckboxVal(contentList.get(2), Constant.DICTIONTRY_PROJECTTYPE);
        pro.setProjectType(StringUtil.isEmpty(projectType) ? "3" : projectType);
        //所属领域不存在为其他（7）
        String researchField = getCheckboxVal(contentList.get(3), Constant.DICTIONTRY_PROJECTFIELD);
        pro.setResearchField(StringUtil.isEmpty(researchField) ? "7" : researchField);
        //国别不存在为国内
        pro.setDomesticOrForeign(StringUtil.isEmpty(contentList.get(4)) ? 0 : contentList.get(4).equals("国内") ? 0 : 1);
        pro.setArea(getAreaNames(contentList.get(5), pro.getDomesticOrForeign()));
        String projectName = contentList.get(6);
        pro.setProjectName(StringUtil.isEmpty(projectName) ? "没有项目标题" : projectName.length() > 128 ? projectName.substring(0, 128) : projectName);
        String introduction = contentList.get(7);
        pro.setIntroduction(StringUtil.isEmpty(introduction) ? null : introduction.length() > 3000 ? introduction.substring(0, 3000) : introduction);
        pro.setKeyWords(contentList.get(8));
        pro.setProjectHolder(contentList.get(9).replaceAll("、|;|；|，", ","));
        pro.setProjectStatus(getDicPid(contentList.get(10), Constant.DICTIONTRY_PROJECTSTATUS));//默认状态：未联系
        pro.setTechnical(getDicPid(contentList.get(11), Constant.DICTIONTRY_PROJECTTECHNICAL));//默认技术成熟度：研发
        pro.setCollectPersonId(contentList.get(21));
        pro.setProjectContactId(StringUtil.isEmpty(contentList.get(22)) ? null : contentList.get(22).replace("E", ""));
        
        ProjectAttr proAttr = new ProjectAttr();
        proAttr.setMarketProspect(contentList.get(12));
        proAttr.setProjectRequirements(contentList.get(13));
        
        Person person = new Person();
        person.setName(contentList.get(14));
        person.setFixedPhone(contentList.get(15));
        person.setTell(contentList.get(16));
//        person.setEmail(contentList.get(17));
        person.setWechat(contentList.get(18));
//        person.setOtherContact(contentList.get(19));
        setEmailAndOtherContact(person, contentList.get(17), contentList.get(19));
        person.setProfessionaField(contentList.get(20));
        person.setSource(7385);//默认专家来源：其他
        person.setType(7384);//默认专家类型：其他
        person.setResearchField("7");//默认专家领域：其他
        person.setDomesticOrForeign(0);//默认国别：国内
        person.setArea("11");//默认地区：北京
        person.setSex(0);//默认性别：男
        ImportProject importProject = new ImportProject(pro, proAttr, person);
        return importProject;
    }
    
    private static void setEmailAndOtherContact(Person person, String emailStr, String otherContactStr) {
        String email = emailStr;
        String otherContact = otherContactStr;
        if (StringUtil.isNotEmpty(emailStr) && emailStr.contains(",")) {
        	String[] emailArr = emailStr.split(",|，|;|；|、");
            email = emailArr[0];
            if (emailArr.length > 1) {
            	emailArr[0] = otherContact;
            	otherContact = Stream.of(emailArr).filter(StringUtil::isNotEmpty).collect(Collectors.joining(","));
            }
        }
        person.setEmail(email);
        person.setOtherContact(otherContact);
    }
    
    public static List<ImportDemand> readImportDemandList(InputStream in) {
        List<ImportDemand> importProjectList = new LinkedList<>();
        List<List<String>> contentLists = readExcel(in);
        contentLists.forEach(contentList -> importProjectList.add(createImportDemand(contentList)));
        return importProjectList;
    }
    
    private static ImportDemand createImportDemand(List<String> contentList) {
        Demand demand = new Demand();
        demand.setSource(getDicPid(contentList.get(0), Constant.DICTIONTRY_PROJECTSOURCE));
        demand.setSourceRemark(contentList.get(1));
        demand.setDemandType(StringUtil.isEmpty(contentList.get(2)) ? "7" : getCheckboxVal(contentList.get(2), Constant.DICTIONTRY_DEMANDTYPE));
        demand.setResearchField(getCheckboxVal(contentList.get(3), Constant.DICTIONTRY_DEMANDFIELD));
        demand.setDomesticOrForeign(contentList.get(4).equals("国内") ? 0 : 1);
        demand.setArea(getAreaNames(contentList.get(5), demand.getDomesticOrForeign()));
        demand.setDemandName(contentList.get(6));
        demand.setDemandContent(contentList.get(7));
        demand.setDemandUnit(contentList.get(8));
        demand.setDemandStatus(getDicPid(contentList.get(9), Constant.DICTIONTRY_DEMANDSTATUS));//默认状态
        demand.setCollectPersonId(contentList.get(16));//人名
        demand.setRemark1(contentList.get(17));
        demand.setRemark2(contentList.get(18));
        
        Person person = new Person();
        person.setName(contentList.get(10));
        person.setFixedPhone(contentList.get(11));
        person.setTell(contentList.get(12));
//        person.setEmail(contentList.get(13));
        person.setWechat(contentList.get(14));
//        person.setOtherContact(contentList.get(15));
        setEmailAndOtherContact(person, contentList.get(13), contentList.get(15));
        person.setSource(7385);//默认专家来源：其他
        person.setType(7384);//默认专家类型：其他
        person.setResearchField("7");//默认专家领域：其他
        person.setDomesticOrForeign(0);//默认国内
        person.setArea("11");//默认北京：11
        ImportDemand importDemand = new ImportDemand(demand, person);
        return importDemand;
    }
    
    /**
     * 从excel导入person，表头为：<b/>
     * 专家来源 来源备注    专家类型    所属领域    国内或国外   所在地区    人才级别    姓名  单位  职务（职称）  专业领域    性别  固定电话    手机  邮箱  微信  其他联系方式
     * @author pdz
     * @date 2018年9月11日
     * @param in
     * @return
     */
    public static List<Person> readImportPersonList(InputStream in) {
        List<Person> importProjectList = new LinkedList<>();
        List<List<String>> contentLists = readExcel(in);
        contentLists.forEach(contentList -> importProjectList.add(createPerson(contentList)));
        return importProjectList;
    }
    
    private static Person createPerson(List<String> contentList) {
        Person person = new Person();
        person.setSource(getDicPid(contentList.get(0), Constant.DICTIONTRY_PROJECTSOURCE));
        person.setRemark1(contentList.get(1));
        person.setType(getDicPid(contentList.get(2), Constant.DICTIONTRY_PERSONTYPE));
        String researchField = getCheckboxVal(contentList.get(3), Constant.DICTIONTRY_PROJECTFIELD);
        //研究领域为空的话默认为其他（7）
        person.setResearchField(StringUtil.isEmpty(researchField) ? "7" : researchField);
        String domesticOrForeign = contentList.get(4);
        //国内国外没有默认为国内（0）
        person.setDomesticOrForeign(StringUtil.isEmpty(domesticOrForeign) ? 0 : domesticOrForeign.equals("国内") ? 0 : 1);
        person.setArea(getAreaNames(contentList.get(5), person.getDomesticOrForeign()));
        person.setTalentLevel(getCheckboxVal(contentList.get(6), Constant.DICTIONTRY_TALENTLEVEL));
        person.setName(contentList.get(7));
        person.setUnit(contentList.get(8));
        person.setTitle(contentList.get(9));
        String professionaField = contentList.get(10);
        person.setProfessionaField(StringUtil.isEmpty(professionaField) ? null : professionaField.length() > 2048 ? professionaField.substring(0, 2048) : professionaField);
        //性别没有的话默认为男（0）
        person.setSex(StringUtil.isEmpty(contentList.get(11)) ? 0 : contentList.get(11).equals("男") ? 0 : 1);
        person.setFixedPhone(contentList.get(12));
        person.setTell(contentList.get(13));
//        person.setEmail(contentList.get(14));
        person.setWechat(contentList.get(15));
//        person.setOtherContact(contentList.get(16));
        setEmailAndOtherContact(person, contentList.get(14), contentList.get(16));
        person.setRetireStatus(getDicPid(contentList.get(17), Constant.DICTIONTRY_PERSONRETIRE));
        String birth = Stream.of(contentList.get(18).split("/")).map(part -> part.length() == 1 ? "0"+part : part).collect(Collectors.joining("/"));
		person.setBirth(birth);
		person.setBirthPlace(contentList.get(19));
		person.setMaxEducation(contentList.get(20));
		person.setSchoolAndMajor(contentList.get(21));
		person.setWebsite(contentList.get(22));
		person.setPersonInfo(contentList.get(23));
		person.setCollectPersonName(contentList.get(24));
		
        return person;
    }
    
    public static List<Person> readImportUpdatePersonList(InputStream in, UnaryOperator<Person> uo) {
        List<Person> importProjectList = new LinkedList<>();
        List<List<String>> contentLists = readExcel(in);
        contentLists.forEach(contentList -> importProjectList.add(createUpdatePerson(contentList, uo)));
        return importProjectList;
    }
    
    private static Person createUpdatePerson(List<String> contentList, UnaryOperator<Person> uo) {
    	Person person = new Person();
    	int expertNumber = Integer.parseInt(contentList.get(0).replace("E", "").trim());
    	System.out.println("expertNumber: " + expertNumber);
		person.setExpertNumber(expertNumber);
    	person = uo.apply(person);
    	person.setResearchFieldInteger(Integer.parseInt(person.getResearchField()));
    	person.setTalentLevelInteger(StringUtil.isEmpty(person.getTalentLevel()) ? null : Integer.parseInt(person.getTalentLevel()));
//    	person.setName(contentList.get(1));
    	person.setType(getDicPid(contentList.get(2), Constant.DICTIONTRY_PERSONTYPE));
    	person.setUnit(contentList.get(3));
    	String researchField = getCheckboxVal(contentList.get(4), Constant.DICTIONTRY_PROJECTFIELD);
    	//研究领域为空的话默认为其他（7）
    	person.setResearchField(StringUtil.isEmpty(researchField) ? "7" : researchField);
    	person.setResearchFieldInteger(StrUtil.stringByByte(person.getResearchField()));
    	
    	String domesticOrForeign = contentList.get(5);
    	//国内国外没有默认为国内（0）
    	person.setDomesticOrForeign(StringUtil.isEmpty(domesticOrForeign) ? 0 : domesticOrForeign.equals("国内") ? 0 : 1);
    	person.setArea(getAreaNames(contentList.get(6), person.getDomesticOrForeign()));
    	return person;
    }
    
    /**
     * 如果没有值，返回默认值北京(11)
     * @author pdz
     * @date 2018年9月6日
     * @param cellStr
     * @param domesticOrForeign
     * @return
     */
    public static String getAreaNames(String cellStr, int domesticOrForeign) {
    	System.out.println(cellStr);
        String areaNames = "11";//北京
        if (StringUtil.isEmpty(cellStr))
            return areaNames;
        if (domesticOrForeign == 0) {//国内
            String[] arr = cellStr.toLowerCase().split("-");
            if (arr.length == 3) {
                areaNames = getDicAreaNames(arr[2], Constant.DICTIONTRY_AREA);
            } else if (arr.length == 2) {
            	areaNames = getDicAreaNames(arr[1], Constant.DICTIONTRY_AREA_CITY);
            } else if (arr.length == 1) {
            	areaNames = getDicAreaNames(arr[0], Constant.DICTIONTRY_AREA_PROVINCE);
            }
        } else 
            areaNames = getDicPid(cellStr, Constant.DICTIONTRY_COUNTRY).toString();
        return areaNames;
    }
    
    /**
     * 根据worth获取names，专用于地区，导入的时候有时候市区不分，容易出错，所以直接用这个方法处理
     * @author pdz
     * @date 2018年11月19日
     * @param areaWorth
     * @param groupname
     * @return
     */
    public static String getDicAreaNames(String areaWorth, String groupName) {
    	return getDicList(groupName).stream()
    			.filter(dic -> dic.getWorth().equals(areaWorth) || dic.getWorth().contains(areaWorth.substring(0, areaWorth.length()-1)))
    			.findAny().map(Dictiontry::getNames).get();
    }

    /**
     * 将在页面表现为复选框的字符串转换成十进制数字，如项目类型、所属领域等，多个值用英文逗号隔开，返回的是数字或以,分隔的数字
     * 如3或1,3,4，如果cellStr为空，返回null
     * @author pdz
     * @date 2018年9月4日
     * @param cellStr
     * @param groupName
     * @return
     */
    private static String getCheckboxVal(String cellStr, String groupName) {
        if (StringUtil.isEmpty(cellStr))
            return null;
        String checkboxStr = Stream.of(cellStr.split(",|，|、|;|；")).filter(StringUtil::isNotEmpty)
                .map(t -> getDicNames(t, groupName)).collect(Collectors.joining(","));
        return checkboxStr;
    }

    /**
     * 根据worth查找出pid
     * @author pdz
     * @date 2018年9月4日
     * @param worth
     * @param groupName
     * @return
     */
    private static Integer getDicPid(String worth, String groupName) {
        System.out.println("getdicPid worth: " + worth);
        return getDicList(groupName).stream().filter(dic -> dic.getWorth().equals(worth.trim())).map(Dictiontry::getPid)
            .findAny().get();
    }
    
    /**
     * 根据worth查找names
     * @author pdz
     * @date 2018年9月4日
     * @param worth
     * @param groupName
     * @return
     */
    private static String getDicNames(String worth, String groupName) {
        System.out.println("getdicnames worth: " + worth);
        return getDicList(groupName).stream().filter(dic -> dic.getWorth().equals(worth.trim())).map(Dictiontry::getNames)
                .findAny().get();
    }

	private static List<Dictiontry> getDicList(String groupName) {
		List<Dictiontry> list = SystemGlobals.getInstance().getDictiontryMap(groupName);
		return list;
	}

    public static void main(String[] args) {
//        List<String> tagList = Arrays.asList("ID", "名字");
//        ArrayList<List<String>> contentLists = new ArrayList<>(3);
//        for (int i = 0; i < 3; i++) {
//            List<String> list = new ArrayList<>();
//            list.add(i+"");
//            list.add("名字"+i);
//            contentLists.add(list);
//        }
//        writeExcel(tagList, contentLists, "abc.xls");
    	
    	
    	System.out.println(String.join(",", "jfa", ""));
    	
    }
    

	/**
	 * 文件下载工具类
	 * xyx
	 * @param request
	 * @param excelFile  传入file文件
	 * @param response
	 * @throws Exception
	 * 2018年10月18日
	 */
	public static void downLoad(HttpServletRequest request,File excelFile,
			HttpServletResponse response) throws Exception {
		
		response.setContentType("text/html,charset=utf-8");

		response.setCharacterEncoding("UTF-8");
		try {
			FileInputStream in = new FileInputStream(excelFile);
			OutputStream fos = response.getOutputStream();
			response.reset();
			response.setContentType("application/x-download");
			response.setHeader("Content-disposition", "attachment;filename=" + excelFile.getName());
			byte[] b = new byte[2048];
			int read;
			while ((read = in.read(b)) != -1) {
				fos.write(b, 0, read);
			}
			fos.flush();
			in.close();
			fos.close();
		} catch (Exception e) {
			e.getMessage();
		}
		//删除服务器上该文件
		excelFile.delete();
	}
	
	
	/**
	 * 下载word
	 * @author pdz
	 * @date 2018年11月13日
	 * @param dataMap 填充到模板中的数据，模板中是${xx}的形式
	 * @param fileName 下载的word文件名
	 * @param template 模板文件名
	 */
	public static void downWord(Map<String, String> dataMap, String fileName, String template, HttpServletRequest request, HttpServletResponse response) {
		File file = new File(fileName);
		Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(ExcelUtil.class, "/templates");
        try(OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), "utf-8");) {
			configuration.getTemplate(template).process(dataMap, out);
		} catch (Exception e) {
			e.printStackTrace();
		} 
        try {
			downLoad(request, file, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 判断批量下载专家至本地是否成功
	 * @author dongli
	 * @date 2019年2月22日
	 * @param request
	 * @param excelFile
	 * @param response
	 * @throws Exception
	 */
	public static boolean downLoad1(HttpServletRequest request,File excelFile,HttpServletResponse response) throws Exception {
		boolean flag = false;
		response.setContentType("text/html,charset=utf-8");
		response.setCharacterEncoding("UTF-8");
		try {
			FileInputStream in = new FileInputStream(excelFile);
			OutputStream fos = response.getOutputStream();
			response.reset();
			response.setContentType("application/x-download");
			response.setHeader("Content-disposition", "attachment;filename=" + excelFile.getName());
			byte[] b = new byte[2048];
			int read;
			while ((read = in.read(b)) != -1) {
				fos.write(b, 0, read);
			}
			fos.flush();
			in.close();
			fos.close();
			flag=true;
		} catch (Exception e) {
			e.getMessage();
		}
		//删除服务器上该文件
		excelFile.delete();
		return flag;
	}

}
